﻿using AutoMapper;
using Microsoft.AspNetCore.Http;
using System;
using System.Net.Http;
using System.Threading.Tasks;
using TomNet.Core;
using TomNet.Data;
using TomNet.Demo.Entity.Entities;
using TomNet.Demo.Repository.Repositories;
using TomNet.Demo.Service.User.Input;
using TomNet.Demo.Service.User.Output;
using TomNet.Entity;
using TomNet.FreeSql;

namespace TomNet.Demo.Service.User
{
    public interface IUserService
    {

        /// <summary>
        /// 添加用户Dto方式，这里应用了auotmap
        /// </summary>
        Task<OpResult<string>> AddAsync(UserAddInput dto);

        /// <summary>
        /// 添加用户
        /// 开启事务
        /// </summary>
        Task<OpResult<string>> InsertAsync(UserAddInput dto);

        /// <summary>
        /// 添加用户
        /// 开启事务
        /// </summary>
        OpResult<string> CreateUser(UserAddInput dto);

        /// <summary>
        /// 查询分页
        /// </summary>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        Task<PageData<UserOutput>> QueryUserAsync(int pageIndex, int pageSize);

        /// <summary>
        /// 用户登录
        /// </summary>
        Task<OpResult<UserEntity>> Login(LoginInput dto);

        /// <summary>
        /// 修改用户密码
        /// 悲观锁方式
        /// </summary>
        OpResult<string> ResetPassword(long id, string pwd);

        /// <summary>
        /// 修改用户密码
        /// 默认乐观锁
        /// </summary>
        Task<OpResult<string>> ResetPwdAsync(long id, string pwd);

    }

    public class UserService : ServiceBase, IUserService
    {
        private readonly IMapper _mapper;
        private readonly IFreeSql _fsql;
        private readonly IMenuRepository _menuRepository;
        private readonly IUserRepository _userRepository;
        private readonly IUserInfoRepository _userInfoRepository;


        public UserService(IMapper mapper,
            IFreeSql fsql,
            IMenuRepository menuRepository,
            IUserRepository userRepository,
            IUserInfoRepository userInfoRepository) : base(null, null)
        {
            _mapper = mapper;
            _fsql = fsql;
            _menuRepository = menuRepository;
            _userRepository = userRepository;
            _userInfoRepository = userInfoRepository;

        }

        /// <summary>
        /// 添加用户
        /// 这里应用了auotmap
        /// </summary>
        public async Task<OpResult<string>> AddAsync(UserAddInput dto)
        {
            var res = new OpResult<string>();
            try
            {
                var entity = _mapper.Map<UserEntity>(dto);
                await _userRepository.InsertAsync(entity);

                //throw new Exception("我是制造麻烦的一个异常");
                var info = new UserInfoEntity { UserId = entity.Id, Zip = dto.Zip };
                await _userInfoRepository.InsertAsync(info);

                return res.OK();
            }
            catch (Exception ex)
            {
                return res.NotOK(status: ApiResultCode.SystemInnerError, msg: ex.Message);
            }
        }


        /// <summary>
        /// 添加用户
        /// 开启事务（AOP事务）
        /// </summary>
        [Transaction]
        public async Task<OpResult<string>> InsertAsync(UserAddInput dto)
        {
            var res = new OpResult<string>();
            try
            {
                
                var entity = _mapper.Map<UserEntity>(dto);
                await _userRepository.InsertAsync(entity);

                // throw new Exception("我是制造麻烦的一个异常");
                var info = new UserInfoEntity { UserId = entity.Id, Zip = dto.Zip };
                await _userInfoRepository.InsertAsync(info);

       
                return res.OK();
            }
            catch (Exception ex)
            {
                return res.NotOK(status: ApiResultCode.SystemInnerError, msg: ex.Message);
            }
        }


        /// <summary>
        /// 添加用户
        /// 开启事务(局部事务)
        /// </summary>
        public OpResult<string> CreateUser(UserAddInput dto)
        {
            var res = new OpResult<string>();
            try
            {
                _fsql.Transaction(() =>
                {
                    var entity = _mapper.Map<UserEntity>(dto);
                    _userRepository.Insert(entity);

                    // throw new Exception("我是制造麻烦的一个异常");
                    var info = new UserInfoEntity { UserId = entity.Id, Zip = dto.Zip };
                    _userInfoRepository.Insert(info);
                });
                return res.OK();
            }
            catch (Exception ex)
            {
                return res.NotOK(status: ApiResultCode.SystemInnerError, msg: ex.Message);
            }
        }

        public async Task<PageData<UserOutput>> QueryUserAsync(int pageIndex, int pageSize)
        {
            var query = await _fsql.Select<UserEntity, UserInfoEntity>()
                  .InnerJoin((user, info) => user.Id == info.UserId)
                  //.Where((user, info) => user.Password == "111")
                  //.WhereIf(false, (user, info) => user.LoginName == "ttt")
                  .Count(out var total)
                  .Page(pageIndex, pageSize)
                  .ToListAsync((user, info) => new UserOutput
                  {
                      Name = user.LoginName
                  });


            PageData<UserOutput> list = new PageData<UserOutput>
            {
                PageNumber = pageIndex,
                PageSize = pageSize,
                TotalCount = total,
                List = query
            };

            return list;
        }
        /// <summary>
        /// 用户登录
        /// </summary>
        public async Task<OpResult<UserEntity>> Login(LoginInput dto)
        {
            var res = new OpResult<UserEntity>();
            try
            {
                var entity = await _userRepository.Where(m => m.LoginName == dto.Name && m.Password == dto.Pass).FirstAsync();
                if (entity != null)
                {
                    return res.OK(data: entity);
                }
                return res.NotOK(status: ApiResultCode.UserLoginError, msg: "账号或密码错误");
            }
            catch (Exception ex)
            {
                return res.NotOK(status: ApiResultCode.SystemInnerError, msg: ex.Message);
            }
        }

        /// <summary>
        /// 修改用户密码
        /// 悲观锁方式
        /// </summary>
        public OpResult<string> ResetPassword(long id, string pwd)
        {
            var res = new OpResult<string>();
            try
            {
                _fsql.Transaction(() =>
                {
                    var user = _userRepository.Select
                        .ForUpdate(true)
                        .Where(m => m.Id == id).ToOne();

                    // 行被锁定，执行它将一直处于等待状态
                    // update UserLogin set Password='123123' where Id=1
                    // 行未锁定，正常执行完毕
                    // update UserLogin set Password='123123' where Id=2

                    if (user != null)
                    {
                        user.Password = pwd;
                        _userRepository.Update(user);
                        res.OK();
                    }
                    else
                    {
                        res.NotOK(status: ApiResultCode.UserNotExist, msg: "用户不存在");
                    }
                });
            }
            catch (Exception ex)
            {
                res.NotOK(status: ApiResultCode.SystemInnerError, msg: ex.Message);
            }

            return res;
        }

        /// <summary>
        /// 修改密码
        /// 默认乐观锁
        /// </summary>
        //[Transaction]
        public async Task<OpResult<string>> ResetPwdAsync(long id, string pwd)
        {
            var res = new OpResult<string>();
            try
            {


                var user = await _userRepository.Select
                    .Where(m => m.Id == id).ToOneAsync();
                // 更新前我们在另一个地方修改数据，制造触发乐观锁的前提
                // update UserLogin set Password = '123123', VersionRow = VersionRow + 1 where Id = 1
                if (user != null)
                {
                    user.Password = pwd;
                    _userRepository.Update(user);
                    res.OK();
                }
                else
                {
                    res.NotOK(status: ApiResultCode.UserNotExist, msg: "用户不存在");
                }

                // 反面教程，直接修改那是不行滴
                //var save = await _userRepository.UpdateDiy
                //                .Set(a => new UserEntity
                //                {
                //                    Password = pwd
                //                })
                //                .Where(m => m.Id == id)
                //                .ExecuteAffrowsAsync();
                ////throw new Exception("我来制造一个麻烦");
                //if (save > 0)
                //{
                //    res.OK();
                //}
                //else
                //{
                //    res.NotOK(status: ApiResultCode.UserNotExist, msg: "用户不存在");
                //}
            }
            catch (Exception ex)
            {
                res.NotOK(status: ApiResultCode.SystemInnerError, msg: ex.Message);
            }
            return res;
        }
    }
}
